<?php
/**
 * BaseController.php
 * @copyright (c) 2011-2020, Hangzhou DOJI Tech Co., Ltd.
 * This is NOT a freeware, use is subject to license terms.
 * @package BaseController.php
 * @link https://www.tingjunapp.com/
 * @author wujun@lanqb.cn
 * @: BaseController.php 310000 2020-11-06 15:23:53 $
 * */

namespace App\Http\Controllers;

use App\Consts\ExceptionCode;
use App\Consts\GlobalConst;
use App\Exceptions\Error;
use App\Models\Cache\CacheKey;
use Illuminate\Support\Facades\Cache;

class BaseController extends Controller
{

    /** @var mixed $user  */
    public $user;

    /** @var string user id */
    public $userId = '';

    /** @var string user identity */
    public $identity = '';

    /** @var string token */
    public $token = '';

    /**
     * init controller before action
     * @return mixed
     */
    /**
     * @param array $parameters
     * @return bool
     */
    public function init($parameters = [])
    {
        // @INIT Implement __INIT() method.
        $parameters = collect($parameters)->toArray();
        foreach ($parameters as $parameter) {
            // user from pc login
            if (array_key_exists('userPcLogin', $parameter)) {
                $this->load($parameter['userPcLogin']);
            }
        }
        return true;
    }

    /**
     * before action
     * @param array $parameters
     * @return mixed
     */
    public function beforeAction($parameters = [])
    {
        return $this->init($parameters);
    }

    /**
     * after action
     * @param array $parameters
     * @return mixed
     */
    public function afterAction($parameters  = [])
    {
        return true;
    }

    /**
     * load data
     * @param array $data
     * @return $this
     */
    public function load($data)
    {
        foreach ($data as $prop => $datum) {
            $this->$prop = $datum;
        }
        return $this;
    }

    /**
     * @param string $method
     * @param array $parameters
     * @return \Symfony\Component\HttpFoundation\Response|bool
     */
    public function callAction($method, $parameters)
    {
        try {
            $this->beforeAction($parameters);
            $result = parent::callAction($method, $parameters);
            $this->afterAction($parameters);
            return $result;
        } catch (\Exception $e) {
            $msg = $e->getMessage();
            $code = $e->getCode() ? : 999;
            if (!isProd()) {
                $msg .= ' at '.$e->getFile().':'.$e->getLine();
            }
            return $this->apiReturn($msg, $code);
        }
    }

    /**
     * get property
     * @param $property
     * @return |null
     */
    public function __get($property)
    {
        if (isset($this->$property)) {
            return $this->$property;
        } else {
            return null;
        }
    }

    /**
     * set property
     * @param $name
     * @param $value
     * @return mixed
     */
    public function __set($name, $value)
    {
        return $this->$name = $value;
    }

    /**
     * 验证access_token是否过期
     * @param $accessToken
     * @return bool
     */
    public function verifyAccessTokenIsExpired($accessToken)
    {
        $secret = GlobalConst::$secret[GlobalConst::LOGIN_PLATFORM_PC]['tokenSecret'];
        $iv = GlobalConst::$secret[GlobalConst::LOGIN_PLATFORM_PC]['tokenIv'];
        $accessToken = openssl_decrypt(base64_decode($accessToken), GlobalConst::TOKEN_ENCRYPT_METHOD, $secret, 0, $iv);

        $expiredTime = substr($accessToken, 8, 8);
        $expiredTime = base_convert($expiredTime, 36, 10);

        return time() - $expiredTime / 1000 >= 0;
    }

    /**
     * 校验access_token
     * @param $accessToken
     * @return bool
     */
    public function verifyAccessTokenInCache($accessToken)
    {
        // 如果cookie或header中的token不在缓存中，说明登录态失效
        $cacheToken = Cache::get(CacheKey::USER_TOKEN);
        if (!$accessToken || !$cacheToken || !in_array($this->token, $cacheToken, true)) {
            return false;
        }
        return true;
    }

    /**
     * 校验用户状态和手机号
     * @return bool|\Illuminate\Http\JsonResponse
     */
    public function verifyUserStatus()
    {
        if (!$this->user) {
            return false;
        }
        // 验证用户状态
        if ($this->user->status !== GlobalConst::USER_STATUS_ACTIVE) {
            return $this->apiReturn('User unauthorized!', ExceptionCode::ABNORMAL);
        }

        // 验证用户是否绑定手机号
        if (!$this->user->phone) {
            return $this->apiReturn('User unauthorized!', ExceptionCode::NOT_BIND_PHONE);
        }

        return false;
    }

    /**
     * api result return
     * [!] 与 Error::handle 区别：
     *     - apiReturn     注重成功返回
     *     - Error::handle 注重错误返回
     * @param mixed $data
     * @param int $code
     * @return \Illuminate\Http\JsonResponse
     */
    public function apiReturn($data = [], $code = 200)
    {
        $message = 'OK';
        $code = intval($code);
        $success = $code == 200 ? true : false;
        if (!$success) {
            $message = Error::getMessage($code);
        }
        $format = [
            'message' => $message,
            'statusCode' => $code,
            'success' => $success,
            'result' => $data,
        ];
        return response()->json($format);
    }

}
